home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Aminet 37
/
Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso
/
Aminet
/
dev
/
cross
/
devpic.lha
/
devpic
/
source
/
picasm
/
pic14bit.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-02-27
|
6KB
|
254 lines
/*
* picasm -- pic14bit.c
*
* Timo Rossi <trossi@iki.fi>
*
*/
#include <stdio.h>
#include "picasm.h"
/*
* Assemble 14-bit PIC code
*/
int
assemble_14bit_mnemonic(int op)
{
long val;
struct symbol *sym;
char *cp;
int t, symtype;
switch(op) {
case KW_SUBLW:
case KW_ANDLW:
case KW_IORLW:
case KW_XORLW:
val = get_expression();
if(expr_error)
return FAIL;
if(val < -0x80 || val > 0xff)
error(0, "8-bit literal out of range");
val &= 0xff; /* this assumes 2-complement negative numbers */
switch(op) {
case KW_SUBLW: gen_code(0x3c00 | val); break;
case KW_ANDLW: gen_code(0x3900 | val); break;
case KW_IORLW: gen_code(0x3800 | val); break;
case KW_XORLW: gen_code(0x3a00 | val); break;
}
break;
case KW_ADDLW:
if(gen_byte_c(0x3e00) != OK)
return FAIL;
break;
case KW_MOVLW:
if(gen_byte_c(0x3000) != OK)
return FAIL;
break;
case KW_ADDWF:
case KW_SUBWF:
case KW_ANDWF:
case KW_IORWF:
case KW_XORWF:
case KW_COMF:
case KW_DECF:
case KW_INCF:
case KW_MOVF:
case KW_DECFSZ:
case KW_INCFSZ:
case KW_RLF:
case KW_RRF:
case KW_SWAPF:
val = get_expression();
if(expr_error)
return FAIL;
if(val < 0 || val > 0x7f)
error(0, "Register file address out of range");
t = 1;
if(token_type == TOK_COMMA) {
get_token();
t = get_expression();
if(expr_error)
return FAIL;
} else {
if(warnlevel > 0)
warning("Destination speficier omitted");
}
val = (val & 0x7f) | (t != 0 ? 0x80 : 0);
switch(op) {
case KW_ADDWF: gen_code(0x0700 | val); break;
case KW_SUBWF: gen_code(0x0200 | val); break;
case KW_ANDWF: gen_code(0x0500 | val); break;
case KW_IORWF: gen_code(0x0400 | val); break;
case KW_XORWF: gen_code(0x0600 | val); break;
case KW_COMF: gen_code(0x0900 | val); break;
case KW_DECF: gen_code(0x0300 | val); break;
case KW_INCF: gen_code(0x0a00 | val); break;
case KW_MOVF: gen_code(0x0800 | val); break;
case KW_DECFSZ: gen_code(0x0b00 | val); break;
case KW_INCFSZ: gen_code(0x0f00 | val); break;
case KW_RLF: gen_code(0x0d00 | val); break;
case KW_RRF: gen_code(0x0c00 | val); break;
case KW_SWAPF: gen_code(0x0e00 | val); break;
}
break;
case KW_CLRF:
case KW_MOVWF:
val = get_expression();
if(expr_error)
return FAIL;
if(val < 0 || val > 0x7f)
error(0, "Register file address out of range");
switch(op) {
case KW_CLRF: gen_code(0x0180 | val); break;
case KW_MOVWF: gen_code(0x0080 | val); break;
}
break;
case KW_BCF:
case KW_BSF:
case KW_BTFSC:
case KW_BTFSS:
val = get_expression();
if(expr_error)
return FAIL;
if(val < 0 || val > 0x7f)
error(0, "Register file address out of range");
if(token_type != TOK_COMMA) {
error(1, "',' expected");
return FAIL;
}
get_token();
t = get_expression();
if(expr_error)
return FAIL;
if(t < 0 || t > 7) {
error(0, "Bit number out of range");
}
val |= (t << 7);
switch(op) {
case KW_BCF: gen_code(0x1000 | val); break;
case KW_BSF: gen_code(0x1400 | val); break;
case KW_BTFSC: gen_code(0x1800 | val); break;
case KW_BTFSS: gen_code(0x1c00 | val); break;
}
break;
case KW_CALL:
case KW_GOTO:
t = 0;
if(token_type == TOK_IDENTIFIER || token_type == TOK_LOCAL_ID) {
symtype =
(token_type == TOK_IDENTIFIER ? SYMTAB_GLOBAL : SYMTAB_LOCAL);
if(symtype == SYMTAB_LOCAL && local_level == 0) {
error(1, "Local symbol outside a LOCAL block");
return FAIL;
}
sym = lookup_symbol(token_string, symtype);
if(sym == NULL || sym->type == SYM_FORWARD) {
if(sym == NULL) {
sym = add_symbol(token_string, symtype);
sym->type = SYM_FORWARD;
}
val = 0;
add_patch(symtype, sym, PATCH11);
t = 1;
get_token();
goto gen_goto_call;
}
}
val = get_expression();
if(expr_error)
return FAIL;
if(val < 0 || val >= prog_mem_size)
error(0, "GOTO/CALL address out of range");
gen_goto_call:
val &= 0x7ff;
switch(op) {
case KW_CALL: gen_code(0x2000 | val); break;
case KW_GOTO: gen_code(0x2800 | val); break;
}
if(t)
list_flags |= LIST_FORWARD;
break;
case KW_TRIS:
t = get_expression();
if(expr_error)
return FAIL;
if(t < 5 || t > 7)
error(0, "Invalid register address for TRIS");
gen_code(0x0060 | t);
if(warnlevel > 1)
warning("TRIS instruction not recommended");
break;
/*
* RETLW allows multiple parameters/strings, for generating lookup tables
*/
case KW_RETLW:
for(;;) {
if(token_type == TOK_STRCONST) {
for(cp = token_string; *cp != '\0'; cp++)
gen_code(0x3400 | (int)((unsigned char)(*cp)));
get_token();
} else {
if(gen_byte_c(0x3400) != OK)
return FAIL;
}
if(token_type != TOK_COMMA)
break;
get_token();
}
break;
case KW_NOP:
gen_code(0x0000);
break;
case KW_CLRW:
gen_code(0x0100);
break;
case KW_OPTION:
gen_code(0x0062);
if(warnlevel > 1)
warning("OPTION instruction not recommended");
break;
case KW_SLEEP:
gen_code(0x0063);
break;
case KW_CLRWDT:
gen_code(0x0064);
break;
case KW_RETFIE:
gen_code(0x0009);
break;
case KW_RETURN:
gen_code(0x0008);
break;
default:
error(1, "Syntax error");
return FAIL;
}
return OK;
}